
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;

using System.Xml;
using System.Xml.XPath;

using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Core;

namespace BackupRestoreDeploy
{
	public class RestoreBizRules : Syrinx.BaseBizRules
	{
		public void executeCompanyRestore(IApplication app, IRuleContext context, IBizObj backup)
		{
			string path = backup.get("filePath").ToString();
			if (File.Exists(path))
				using (ZipFile zipFile = new ZipFile(path))
				{
					context.RuleGroup.execute(context, "executeCompanyRestoreFromZip", backup, zipFile);
					//Because the order of features in the app config is what controls the order of post extends on
					//biz rules, this call to executeLastSetRestoreFromZip allows restores to be called after the bulk
					//of the others.  Currently, this is important for usermnagement because a restore of users current
					//causes problems for the current user running the restore.
					context.RuleGroup.execute(context, "executeLastSetRestoreFromZip", backup, zipFile);
				}
		}

		public void executeLastSetRestoreFromZip(IApplication app, IRuleContext context, IBizObj backup, ZipFile zipFile)
		{
		}

		public void executeCompanyRestoreFromZip(IApplication app, IRuleContext context, IBizObj backup, ZipFile zipFile)
		{
			string root = app.resMgr.resolve("$ConfigParam1$");
			if (root.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
				root = root.Substring(7);
			IBizObj backupCompany = ((IBizObjList)backup.get("backupCompanies"))[0];
			IBizObj restoreCompany = ((IBizObjList)backup.get("restoreCompanies"))[0];
			bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;

			if (!restoreToSameCompany)
			{
				IResults rc = app.ruleMgr.execute("isShortNameUnique", restoreCompany.get("shortName").ToString());
				if (rc.ExceptionInfo == null && (bool)rc.CallResults == true)
				{
					rc = app.ruleMgr.execute(context, "newCompanySignUp", restoreCompany, null, null, true);
					if (rc.ExceptionInfo != null)
						throw new BackupRestoreDeployException("error ecreating company on processNewSignup.", rc.ExceptionInfo);

					restoreCompany.isNew = false;
					restoreCompany.put("contact.id", new Swaf.BGuid.Guid());
					restoreCompany.put("contact.companyId", restoreCompany.get("id"));
					IBizObj contactType = App.appData["contactOptions.types.(name:Company)"] as IBizObj;
					restoreCompany.put("contact.typeId", contactType.get("id"));
					rc = app.ruleMgr.execute(context, "updateCompany", restoreCompany);
					if (rc.ExceptionInfo != null)
						throw new BackupRestoreDeployException("error on updateCompany from processNewSignup.", rc.ExceptionInfo);

					rc = app.ruleMgr.execute(context, "updateCompanyArticleLimits", restoreCompany, new object[] { app, context, restoreCompany });
					if (rc.ExceptionInfo != null)
						throw new BackupRestoreDeployException("error on updateCompanyArticleLimits from processNewSignup.", rc.ExceptionInfo);

					rc = app.ruleMgr.execute(context, "updateCompanyImageCacheLimits", restoreCompany.get("limits"));
					if (rc.ExceptionInfo != null)
						throw new BackupRestoreDeployException("error on updateCompanyImageCacheLimits from processNewSignup.", rc.ExceptionInfo);
				}
			}

			Regex pathRegex = new Regex(@"^bu[\\/]([^/\\]+)[/\\](.*)", RegexOptions.IgnoreCase);
			Match m;
			string baseDir = Cmn.pathCombine(root, (string)restoreCompany.get("shortName"));
			for (int pos = 0; pos < zipFile.Count; pos++)
			{
				try
				{
					ZipEntry entry = zipFile[pos];
					string entryName = entry.Name;
					if (entry.IsFile && (m = pathRegex.Match(entryName)).Success && m.Groups[1].Value.CompareTo(backupCompany.get("shortName")) == 0)
					{
						int b;
						string destinationPath = Cmn.pathCombine(baseDir, m.Groups[2].Value);
						FileInfo f = new FileInfo(destinationPath);
						Directory.CreateDirectory(f.DirectoryName);
						using (StreamReader sr = new StreamReader(zipFile.GetInputStream(pos)))
						using (FileStream fileOut = File.Create(destinationPath))
						{
							while ((b = sr.Read()) != -1)
								fileOut.WriteByte((byte)b);
						}
					}
				}
				catch (Exception e)
				{
					//TODO: Log, but dont throw
				}
			}
		}
	}
}
